/*
 * http://ajaxorg.github.com/ace-builds/kitchen-sink.html
 */
$(document).ready( function() {
	window.require("ace/lib/fixoldbrowsers");
	window.require("ace/config").init();
	var env = {};
	
	var dom = window.require("ace/lib/dom");
	var event = window.require("ace/lib/event");
	var theme = window.require("ace/theme/textmate");
	var EditSession = window.require("ace/edit_session").EditSession;
	var UndoManager = window.require("ace/undomanager").UndoManager;
	
	var vim = window.require("ace/keyboard/vim").handler;
	var emacs = window.require("ace/keyboard/emacs").handler;
	var HashHandler = window.require("ace/keyboard/hash_handler").HashHandler;
	
	var Renderer = window.require("ace/virtual_renderer").VirtualRenderer;
	var Editor = window.require("ace/editor").Editor;
	var MultiSelect = window.require("ace/multi_select").MultiSelect;
	
	// workers do not work for file:
	if (location.protocol == "file:")
	    EditSession.prototype.$useWorker = false;
	/************** modes ***********************/
	var modes = [];
	function getModeFromPath(path) {
	    var mode = modesByName.text;
	    for (var i = 0; i < modes.length; i++) {
	        if (modes[i].supportsFile(path)) {
	            mode = modes[i];
	            break;
	        }
	    }
	    return mode;
	};
	
	var Mode = function(name, desc, extensions) {
	    this.name = name;
	    this.desc = desc;
	    this.mode = "ace/mode/" + name;
	    this.extRe = new RegExp("^.*\\.(" + extensions + ")$", "g");
	};
	
	Mode.prototype.supportsFile = function(filename) {
	    return filename.match(this.extRe);
	};
	
	var modesByName = {
	    c9search:   ["C9Search"     , "c9search_results"],
	    coffee:     ["CoffeeScript" , "coffee|^Cakefile"],
	    coldfusion: ["ColdFusion"   , "cfm"],
	    csharp:     ["C#"           , "cs"],
	    css:        ["CSS"          , "css"],
	    diff:       ["Diff"         , "diff|patch"],
	    golang:     ["Go"           , "go"],
	    groovy:     ["Groovy"       , "groovy"],
	    haxe:       ["haXe"         , "hx"],
	    html:       ["HTML"         , "htm|xhtml"], // html move to php,html template file has php tag.
	    c_cpp:      ["C/C++"        , "c|cc|cpp|cxx|h|hh|hpp"],
	    clojure:    ["Clojure"      , "clj"],
	    java:       ["Java"         , "java"],
	    javascript: ["JavaScript"   , "js"],
	    json:       ["JSON"         , "json"],
	    jsx:        ["JSX"          , "jsx"],
	    latex:      ["LaTeX"        , "latex|tex|ltx|bib"],
	    less:       ["LESS"         , "less"],
	    liquid:     ["Liquid"       , "liquid"],
	    lua:        ["Lua"          , "lua"],
	    luapage:    ["LuaPage"      , "lp"], // http://keplerproject.github.com/cgilua/manual.html#templates
	    markdown:   ["Markdown"     , "md|markdown"],
	    ocaml:      ["OCaml"        , "ml|mli"],
	    perl:       ["Perl"         , "pl|pm"],
	    pgsql:      ["pgSQL"        , "pgsql"],
	    php:        ["PHP"          , "php|phtml|html"],
	    powershell: ["Powershell"   , "ps1"],
	    python:     ["Python"       , "py"],
	    ruby:       ["Ruby"         , "ru|gemspec|rake|rb"],
	    scad:       ["OpenSCAD"     , "scad"],
	    scala:      ["Scala"        , "scala"],
	    scss:       ["SCSS"         , "scss|sass"],
	    sh:         ["SH"           , "sh|bash|bat"],
	    sql:        ["SQL"          , "sql"],
	    svg:        ["SVG"          , "svg"],
	    tcl:        ["Tcl"          , "tcl"],
	    text:       ["Text"         , "txt"],
	    textile:    ["Textile"      , "textile"],
	    xml:        ["XML"          , "xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl"],
	    xquery:     ["XQuery"       , "xq"],
	    yaml:       ["YAML"         , "yaml"]
	};
	for (var name in modesByName) {
	    var mode = modesByName[name];
	    mode = new Mode(name, mode[0], mode[1])
	    modesByName[name] = mode;
	    modes.push(mode);
	}
	/*********** demo documents ***************************/
	
	function initDoc(file, path, doc) {
	    if (doc.prepare)
	        file = doc.prepare(file);
	
	    var session = new EditSession(file);
	    session.setUndoManager(new UndoManager());
	    doc.session = session;
	    doc.path = path;
	    if (doc.wrapped) {
	    	session.setTabSize(4);
	    	session.setUseSoftTabs(true);
	        session.setUseWrapMode(true);
	        session.setFoldStyle("markbegin");
	    	env.editor.setShowFoldWidgets(true);
	    	env.editor.setHighlightActiveLine(true);
	        session.setWrapLimitRange(null, null);
	    }
	    var mode = getModeFromPath(path)
	    session.modeName = mode.name;
	    session.setMode(mode.mode);
	}
	if (window.require && window.require.s) try {
	    for (var path in window.require.s.contexts._.loaded) {
	        if (path.indexOf("!") != -1)
	            path = path.split("!").pop();
	        else
	            path = path + ".js";
	        ownSource[path] = ""
	    }
	} catch(e) {}
	
	/*********** create editor ***************************/
	var container = document.getElementById("ace_editor_area");
	
	
	env.editor = ace.edit("ace_editor_area");
	window.env = env;
	env.editor.setAnimatedScroll(true);
	
	var consoleEl = dom.createElement("div");
	container.appendChild(consoleEl);
	consoleEl.style.position="fixed"
	consoleEl.style.bottom = "1px"
	consoleEl.style.right = 0
	consoleEl.style.background = "white"
	consoleEl.style.border = "1px solid #baf"
	consoleEl.style.zIndex = "100"
	var cmdLine = new singleLineEditor(consoleEl);
	cmdLine.editor = env.editor;
	env.editor.cmdLine = cmdLine;
	
	env.editor.commands.addCommands([{
	    name: "gotoline",
	    bindKey: {win: "Ctrl-L", mac: "Command-L"},
	    exec: function(editor, line) {
	        if (typeof line == "object") {
	            var arg = this.name + " " + editor.getCursorPosition().row;
	            editor.cmdLine.setValue(arg, 1)
	            editor.cmdLine.focus()
	            return
	        }
	        line = parseInt(line, 10);
	        if (!isNaN(line))
	            editor.gotoLine(line);
	    },
	    readOnly: true
	}, {
	    name: "find",
	    bindKey: {win: "Ctrl-F", mac: "Command-F"},
	    exec: function(editor, needle) {
	        if (typeof needle == "object") {
	            var arg = this.name + " " + editor.getCopyText()
	            editor.cmdLine.setValue(arg, 1)
	            editor.cmdLine.focus()
	            return
	        }
	        editor.find(needle);
	    },
	    readOnly: true
	}, {
	    name: "focusCommandLine",
	    bindKey: "shift-esc",
	    exec: function(editor, needle) { editor.cmdLine.focus(); },
	    readOnly: true
	}])
	
	cmdLine.commands.bindKeys({
	    "Shift-Return|Ctrl-Return|Alt-Return": function(cmdLine) { cmdLine.insert("\n")},
	    "Esc|Shift-Esc": function(cmdLine){ cmdLine.editor.focus(); },
	    "Return": function(cmdLine){
	        var command = cmdLine.getValue().split(/\s+/);
	        var editor = cmdLine.editor;
	        editor.commands.exec(command[0], editor, command[1]);
	        editor.focus();
	    },
	})
	
	cmdLine.commands.removeCommands(["find", "gotoline", "findall", "replace", "replaceall"])
	
	/**
	 * This demonstrates how you can define commands and bind shortcuts to them.
	 */
	
	function savefile(filename,content){
		var url = ADMIN_BASEURL+"/admin/ace/editors/savefile";
		jQuery.post(url,{'name':filename,'content':content},
			function (data) {showSuccessMessage(data.msg);},"json");
	}
	
	var commands = env.editor.commands;
	commands.addCommand({
	    name: "save",
	    bindKey: {win: "Ctrl-S", mac: "Command-S"},
	    exec: function() {
	    	var selected = maintab.tabs( "option", "active" );
        	var cur_tab = $('.ui-tabs-nav:first li',maintab).eq(selected);
        	cur_tab.find('.ui-ace-save').trigger('click');
        	// trigger save file function.
	    	// alert("Fake Save File");
	    	return false;
	    }
	});
	
	var keybindings = {
	    // Null = use "default" keymapping
	    ace: null,
	    vim: vim,
	    emacs: emacs,
	    // This is a way to define simple keyboard remappings
	    custom: new HashHandler({
	        "gotoright":      "Tab",
	        "indent":         "]",
	        "outdent":        "[",
	        "gotolinestart":  "^",
	        "gotolineend":    "$"
	     })
	};
	
	
	
	/*********** manage layout ***************************/
	var consoleHight = 20;
	/*
	$(window).resize(function(){	
		var left = env.split.$container.offsetLeft;
	    var width = $(window).width()-$('.ui-layout-west').width()-left-10;    
	    container.style.width = width + "px";
	    container.style.height = document.documentElement.clientHeight - consoleHight-110 + "px";
	    env.split.resize();
	
	    consoleEl.style.width = width + "px";
	    cmdLine.resize()
	}).trigger('resize');*/
	
	bindDropdown("soft_wrap", function(value) {
	    var session = env.editor.getSession();
	    var renderer = env.editor.renderer;
	    switch (value) {
	        case "off":
	            session.setUseWrapMode(false);
	            renderer.setPrintMarginColumn(80);
	            break;
	        case "120":
	            session.setUseWrapMode(true);
	            session.setWrapLimitRange(120, 120);
	            renderer.setPrintMarginColumn(120);
	            break;
	        case "80":
	            session.setUseWrapMode(true);
	            session.setWrapLimitRange(80, 80);
	            renderer.setPrintMarginColumn(80);
	            break;
	        case "free":
	            session.setUseWrapMode(true);
	            session.setWrapLimitRange(null, null);
	            renderer.setPrintMarginColumn(80);
	            break;
	    }
	});
	bindDropdown("fontsize", function(value) {
		document.getElementById('ace_editor_area').style.fontSize=value;
	});
	bindDropdown("folding", function(value) {
	    env.editor.getSession().setFoldStyle(value);
	    env.editor.setShowFoldWidgets(value !== "manual");
	});
	bindDropdown("keybinding", function(value) {
	    env.editor.setKeyboardHandler(keybindings[value]);
	});
	function bindDropdown(id, callback) {
	    var el = document.getElementById(id);
	    if (localStorage && localStorage.getItem(id))
	        el.value = localStorage.getItem(id);
	
	    var onChange = function() {
	        callback(el.value);
	        //saveOption(el);
	    };
	
	    el.onchange = onChange;
	    onChange();
	}
	/************** dragover ***************************/
	event.addListener(container, "dragover", function(e) {
	    return event.preventDefault(e);
	});
	
	event.addListener(container, "drop", function(e) {
	    var file;
	    try {
	        file = e.dataTransfer.files[0];
	        if (window.FileReader) {
	            var reader = new FileReader();
	            reader.onload = function() {
	                var mode = getModeFromPath(file.name);
	
	                env.editor.session.doc.setValue(reader.result);
	                modeEl.value = mode.name;
	                env.editor.session.setMode(mode.mode);
	                env.editor.session.modeName = mode.name;
	            };
	            reader.readAsText(file);
	        }
	        return event.preventDefault(e);
	    } catch(err) {
	        return event.stopEvent(e);
	    }
	});
	
	// add multiple cursor support to editor
	window.require("ace/multi_select").MultiSelect(env.editor);
	
	
	
	function singleLineEditor(el) {
	    var renderer = new Renderer(el);
	    renderer.scrollBar.element.style.display = "none";
	    renderer.scrollBar.width = 0;
	    renderer.content.style.height = "auto";
	
	    renderer.screenToTextCoordinates = function(x, y) {
	        var pos = this.pixelToScreenCoordinates(x, y);
	        return this.session.screenToDocumentPosition(
	            Math.min(this.session.getScreenLength() - 1, Math.max(pos.row, 0)),
	            Math.max(pos.column, 0)
	        );
	    };
	    // todo size change event
	    renderer.$computeLayerConfig = function() {
	        var longestLine = this.$getLongestLine();
	        var firstRow = 0;
	        var lastRow = this.session.getLength();
	        var height = this.session.getScreenLength() * this.lineHeight;
	
	        this.scrollTop = 0;
	        var config = this.layerConfig;
	        config.width = longestLine;
	        config.padding = this.$padding;
	        config.firstRow = 0;
	        config.firstRowScreen = 0;
	        config.lastRow = lastRow;
	        config.lineHeight = this.lineHeight;
	        config.characterWidth = this.characterWidth;
	        config.minHeight = height;
	        config.maxHeight = height;
	        config.offset = 0;
	        config.height = height;
	
	        this.$gutterLayer.element.style.marginTop = 0 + "px";
	        this.content.style.marginTop = 0 + "px";
	        this.content.style.width = longestLine + 2 * this.$padding + "px";
	        this.content.style.height = height + "px";
	        this.scroller.style.height = height + "px";
	        this.container.style.height = height + "px";
	    };
	    renderer.isScrollableBy=function(){return false};
	
	    var editor = new Editor(renderer);
	    new MultiSelect(editor);
	    editor.session.setUndoManager(new UndoManager());
	
	    editor.setHighlightActiveLine(false);
	    editor.setShowPrintMargin(false);
	    editor.renderer.setShowGutter(false);
	    // editor.renderer.setHighlightGutterLine(false);
	    return editor;
	};
	
	env.editor.setTheme("ace/theme/dreamweaver");
	env.editor.session.setMode("ace/mode/javascript");
	var EditSession = window.require("ace/edit_session").EditSession
	var session = env.editor.getSession();
	session.setTabSize(4);
	session.setUseSoftTabs(true);
	document.getElementById('ace_editor_area').style.fontSize='12px';
	//默认自动换行    
	session.setUseWrapMode(true);
	//env.editor.setReadOnly(true); // 设置只读模式
	
	
	function setSession(session) {
	    var session = env.editor.setSession(session);
	    env.editor.focus();
	}
	
	    
	//    maintab.bind( "tabsselect", function(event, ui) {
	//  alert($(ui.tab).html());
	//});
	
	$('#tpl-editor').hide();   
	//$( ".selector" ).on( "tabsactivate", function( event, ui ) {} );
	/**切换tab时设置当前编辑的文件，打开文件的事件在dynatree的点击事件中**/
	maintab.bind( "tabsactivate", function(event, ui) { //tabsselect
		// todo,先选择第一个编辑，设置完ace的内容后，再切换到旧的选择的表情项（可能是ace或是ckeditor）
		var st = $(ui.newTab).find('a:first').attr('href'); //tab
		var name = st.replace(/#maintab_/g,'');	
		var doc = fileCache[name];
		if (doc && doc.session){
			setSession(doc.session);
			$('#tpl-editor').appendTo(st).show();
		}
		
	});
	
	//--- Implement Cut/Copy/Paste --------------------------------------------
	var clipboardNode = null; /* 剪切板的借点 */
	var pasteMode = null; // 操作动作，cut,copy,paste
	
	function copyPaste(action, node) {
	  switch( action ) {
	  case "cut":
	  case "copy":
	    clipboardNode = node;
	    pasteMode = action;
	    break;
	  case "paste":
	    if( !clipboardNode ) {
	      alert("Clipoard is empty.");
	      break;
	    }
	    if( pasteMode == "cut" ) {
	      // Cut mode: check for recursion and remove source
	      var isRecursive = false;
	      var cb = clipboardNode.toDict(true, function(dict){
	        // If one of the source nodes is the target, we must not move
	        if( dict.key == node.data.key )
	          isRecursive = true;
	      });
	      if( isRecursive ) {
	        alert("Cannot move a node to a sub node.");
	        return;
	      }
	      node.addChild(cb);
	      clipboardNode.remove();
	    } else {
	      // Copy mode: prevent duplicate keys:
	      var cb = clipboardNode.toDict(true, function(dict){
	        dict.title = "Copy of " + dict.title;
	        delete dict.key; // Remove key, so a new one will be created
	      });
	      node.addChild(cb);
	    }
	    clipboardNode = pasteMode = null;
	    break;
	  default:
	    alert("Unhandled clipboard action '" + action + "'");
	  }
	};
	
	// --- Contextmenu helper --------------------------------------------------
	function bindContextMenu(span) {
	  // Add context menu to this node:
	  $(span).contextMenu({menu: "myMenu"}, function(action, el, pos) {
	    // The event was bound to the <span> tag, but the node object
	    // is stored in the parent <li> tag
	    var node = $.ui.dynatree.getNode(el);
	    switch( action ) {
	    case "cut":
	    case "copy":
	    case "paste":
	      copyPaste(action, node);
	      break;
	    case "edit":
	        $(el).trigger('click'); // trigger click event.
	        break;
	    default:
	      alert("Todo: appply action '" + action + "' to node " + node);
	    }
	  });
	};

	jQuery(function(){

		// edit default file.
		if(edit_file_path && save_file_path){
			var name = save_file_path.replace(/\\/g,'_').replace(/\/|\.|:/g,'_');
				var doc = fileCache[name];
				if(typeof doc == "undefined"){
					doc = {};
					fileCache[name] = doc;
				}
				doc.name = name;
				doc.wrapped = true;
				//maintab.tabs('add',st,tab_title);
				var st = "#maintab_"+name;
				var tab_title = edit_file_name;
					var  tabTemplate = "<li><a href='#{href}'>#{label}</a> <span class='ui-icon ui-icon-close' role='presentation'>Remove Tab</span></li>";
				    var  li = $( tabTemplate.replace( /#\{href\}/g,st).replace( /#\{label\}/g, tab_title ) );
				    maintab.find( ".ui-tabs-nav:first" ).append( li );
				    maintab.append( "<div id='" + st.substring(1) + "'></div>" );
				    maintab.tabs( "refresh" );
				    maintab.tabs( "option", "active", maintab.find( ".ui-tabs-nav:first li").size()-1);
					$(st).css('position','relative');
					$('#tpl-editor').appendTo(st);
					var path = ADMIN_BASEURL+"/admin/ace/editors/loadfile?file="+edit_file_path;
					// x,为ajax返回的文件内容  var net = window.require("ace/lib/net");
					//net.get(path, function(x) {
					//        initDoc(x, path, doc);
					//        setSession(doc.session)
					//});
					setSession(new EditSession("loading content..."));
					$('#tpl-editor').show();
					$.ajax({
						url: path,
						type: "GET",
						dataType: "html",
						complete : function (req, err) {
							//fileCache 会存储每个doc的session对象。
							initDoc(req.responseText, path, doc);
					        setSession(doc.session);
					        doc.session.getDocument().on('change',function(){
					        	var selected = maintab.tabs( "option", "active" );
					        	var cur_tab = $('.ui-tabs-nav li',maintab).eq(selected);
					        	if(cur_tab.find('.ui-ace-save').size()==0){
					        		cur_tab.find('a').after('<span class="ui-ace-save ui-icon ui-icon-disk" title="Save File"></span>');
					        		cur_tab.find('.ui-ace-save').click(function(){
					        			savefile(save_file_path,doc.session.getValue());
					        		});
					        	}
					        });
					        
						}
					});
		} // edit init file end.



		jQuery("#leftmenucontent").dynatree({
			title: "Lazy loading sample",
			//fx: { height: "toggle", duration: 200 },
			autoFocus: false, // Set focus to first child, when expanding or lazy-loading.
			// In real life we would call a URL on the server like this:
          initAjax: {
              url: ADMIN_BASEURL+"/admin/ace/editors/listfolder.json",
              data: { mode: "funnyMode" }
          },
          onCreate: function(node, span){
              bindContextMenu(span);
            },

			onActivate: function(node) {
				jQuery("#echoActive").text("" + node + " (" + node.getKeyPath()+ ")");
			},
			onClick: function(node, event) {
				if( $(".contextMenu:visible").length > 0 ){
			          $(".contextMenu").hide();
			    }

				if( node.data.isFolder ){
					return;
				}
				$('#tpl-editor').hide();
				
				var name = node.data.key.replace(/\\/g,'_').replace(/\/|\.|:/g,'_');
				var doc = fileCache[name];
				if(typeof doc == "undefined"){
					doc = {};
					fileCache[name] = doc;
				}
				doc.name = name;
				doc.wrapped = true;
				
				var tab_title = node.data.title;
				$("#leftmenucontent li").find('.ui-state-highlight').removeClass('ui-state-highlight');
				$(this).addClass('ui-state-highlight');
				
				var st = "#maintab_"+name;
				if($(st).html() != null ) {
					maintab.find( ".ui-tabs-nav:first li").each(function(i){
						var href = $(this).find('a:first').attr('href');
						if(href.substring(0,1)!='#'){ //ie7,等href包含了当前的网站，去除#前面的项
							var strs = href.split("#");
							href = '#'+strs[1];
						}						
						if(href==st){
							maintab.tabs( "option", "active", i);
						}
					});
					$('#tpl-editor').appendTo(st).show();					
			        setSession(doc.session);
				} else {
					//maintab.tabs('add',st,tab_title);
					var  tabTemplate = "<li><a href='#{href}'>#{label}</a> <span class='ui-icon ui-icon-close' role='presentation'>Remove Tab</span></li>";
				    var  li = $( tabTemplate.replace( /#\{href\}/g,st).replace( /#\{label\}/g, tab_title ) );
				    maintab.find( ".ui-tabs-nav:first" ).append( li );
				    maintab.append( "<div id='" + st.substring(1) + "'></div>" );
				    maintab.tabs( "refresh" );
				    maintab.tabs( "option", "active", maintab.find( ".ui-tabs-nav:first li").size()-1);
					$(st).css('position','relative');
					$('#tpl-editor').appendTo(st);
					var path = ADMIN_BASEURL+"/admin/ace/editors/loadfile?file="+node.data.key;
					// x,为ajax返回的文件内容  var net = window.require("ace/lib/net");
					//net.get(path, function(x) {
					//        initDoc(x, path, doc);
					//        setSession(doc.session)
					//});
					
					setSession(new EditSession("loading content..."));
					$('#tpl-editor').show();
					$.ajax({
						url: path,
						type: "GET",
						dataType: "html",
						complete : function (req, err) {
							//fileCache 会存储每个doc的session对象。
							initDoc(req.responseText, path, doc);
					        setSession(doc.session);
					        doc.session.getDocument().on('change',function(){
					        	var selected = maintab.tabs( "option", "active" );
					        	var cur_tab = $('.ui-tabs-nav li',maintab).eq(selected);
					        	if(cur_tab.find('.ui-ace-save').size()==0){
					        		cur_tab.find('a').after('<span class="ui-ace-save ui-icon ui-icon-disk" title="Save File"></span>');
					        		cur_tab.find('.ui-ace-save').click(function(){
					        			savefile(node.data.key,doc.session.getValue());
					        		});
					        	}
					        });
					        
						}
					});
					
				}
			},

			onLazyRead: function(node){
				// In real life we would call something like this:
            	node.appendAjax({
            	    url: ADMIN_BASEURL+"/admin/ace/editors/listfolder.json",
		            data: {key: node.data.key,
            		       mode: "funnyMode"
                    }
              });
			}
		});	// dynatree over.
		
	});
});